import { Parser } from 'expr-eval'

/**
 * 初始化树
 * @param {*} records 平板数据
 * @param {*} keys id和parentId字段映射
 * @param {*} options 其他参数信息
 * @param {*} options.ignoreLeaf 其他参数信息-忽略生成叶子节点
 */
export const initTree = function (records, keys, options = {}) {
  const map = {}
  // 初始化id和parentId
  if (!keys) {
    keys = { id: 'id', parentId: 'parentId' }
  }
  const {
    ignoreLeaf
  } = options
  const idField = keys.id
  const parentField = keys.parentId
  const parentRecords = []
  // 生成map对象
  records.forEach(rec => {
    if (!ignoreLeaf) {
      rec.isLeaf = true
    }
    rec.childNodes = []
    map[rec[idField]] = rec
  })

  // 生成childNodes数组
  records.forEach(rec => {
    const parent = map[rec[parentField]]
    if (parent) {
      parent.childNodes.push(rec)
      if (!ignoreLeaf) {
        parent.isLeaf = false
      }
    } else {
      parentRecords.push(rec)
    }
  })

  return { map, records, parentRecords }
}

/**
 * 循环遍历过滤树方法, 筛选出对应的父节点和子节点
 * @param {*} records 树集合
 * @param {*} strFilters 模糊匹配过滤条件 [{ field: 'a', value: '123' }]
 */
export const filterTree = function (records, strFilters) {
  const result = []
  for (const record of records) {
    // 如果当前节点满足筛选条件，则将所有子节点添加到返回结果中
    if (matchStrValue(record, strFilters)) {
      const childArrs = getChildNodes(record)
      result.push(record, ...childArrs)
    } else if (record.childNodes.length) { // 否则循环遍历子节点
      const matchArrs = filterTree(record.childNodes, strFilters)
      // 如果子节点匹配成功，则将匹配的记录和当前记录添加到返回结果中
      if (matchArrs.length) {
        result.push(record, ...matchArrs)
      }
    }
  }

  return result
}

/**
 * 循环遍历获取子节点数据
 * @param {*} record 传入节点
 */
const getChildNodes = function (record) {
  const result = []
  for (const node of record.childNodes) {
    const childArrs = getChildNodes(node)
    result.push(node, ...childArrs)
  }
  return result
}

/**
 * 判断字符串条件是否匹配记录
 * @param {*} record 指定记录
 * @param {*} strFilters 模糊匹配过滤条件 [{ field: 'a', value: '123' }]
 */
const matchStrValue = function (record, strFilters) {
  let result = false
  for (const filter of strFilters) {
    const value = (record[filter.field] || '').trim()
    const filterValue = (filter.value || '').trim()
    result = result || !filterValue || value.indexOf(filterValue) !== -1
    if (result) {
      break
    }
  }
  return result
}

/**
 * 循环遍历过滤树方法, 筛选出对应的父节点和子节点
 * @param {*} records 树集合
 * @param {*} options 筛选条件 {}
 */
export const filterAllNodes = function (records, options) {
  const result = []
  for (const record of records) {
    // 如果当前节点满足筛选条件，则将所有子节点添加到返回结果中
    if (matchValue(record, options.filters)) {
      const childArrs = getChildNodes(record)
      result.push(record, ...childArrs)
    } else if (record.childNodes.length) { // 否则循环遍历子节点
      const matchArrs = filterAllNodes(record.childNodes, options)
      // 如果子节点匹配成功，则将匹配的记录和当前记录添加到返回结果中
      if (matchArrs.length) {
        result.push(record, ...matchArrs)
      }
    }
  }

  return result
}

/**
 * 循环遍历过滤树方法, 筛选对应的叶子节点
 * @param {*} records 树集合
 * @param {*} options 筛选条件 {}
 */
export const filterLeafNodes = function (records, options) {
  const result = []
  for (const record of records) {
    // 如果是父节点，则遍历筛选子节点
    if (record.childNodes.length) {
      const matchArrs = filterLeafNodes(record.childNodes, options)
      result.push(...matchArrs)
    } else if (matchValue(record, options.filters)) { // 否则判断当前节点是否满足筛选条件
      result.push(record)
    }
  }

  return result
}

/**
 * 判断筛选条件是否匹配记录
 * @param {*} record 指定记录
 * @param {*} strFilters 模糊匹配过滤条件 [{ field: 'a', value: '123', rule: 'like', operator: '>=' }]
 */
const matchValue = function (record, filters) {
  let result = true
  if (!filters.length) {
    return result
  }
  for (const filter of filters) {
    if (filter.filters) {
      result = result && matchOr(record, filter.filters)
    } else {
      result = result && matchByRule(record, filter)
    }
    if (!result) {
      break
    }
  }
  return result
}

/**
 * 匹配规则：或条件
 * @param {*} record 指定记录
 * @param {*} filters 过滤条件 [{ field: 'a', value: '123', rule: 'or', operator: '>=' }]
 */
const matchOr = function (record, filters) {
  let result = false
  if (!filters.length) {
    return true
  }
  for (const filter of filters) {
    result = result || matchByRule(record, filter)
    if (result) {
      break
    }
  }
  return result
}

/**
 * 匹配规则：按指定运算符
 * @param {*} record 指定记录
 * @param {*} filter 过滤条件 { field: 'a', value: '123', rule: 'like', operator: '>=' }
 */
const matchByRule = function (record, filter) {
  const result = false
  if (record[filter.field] === undefined) {
    return result
  }

  switch (filter.rule) {
    case 'like':
      return matchByFuzzy(record, filter)
    case 'array':
      return matchByArray(record, filter)
    default:
      return matchByOperator(record, filter)
  }
}

// 运算符匹配
const matchByOperator = function (record, filter) {
  const value = record[filter.field]
  const filterValue = filter.value
  if (filterValue === null) {
    return value === null
  }

  if (value === null) {
    return false
  }
  const operator = filter.operator || '=='
  let result = false
  try {
    result = Parser.evaluate(`${value}${operator}${filterValue}`)
  } catch (err) {
    console.log(err)
  }
  return result
}

// 模糊匹配
const matchByFuzzy = function (record, filter) {
  const value = (record[filter.field] || '').trim()
  const filterValue = (filter.value || '').trim()
  return value.indexOf(filterValue) !== -1
}

// 数组匹配
const matchByArray = function (record, filter) {
  return filter.value.some(item => item === record[filter.field])
}
